package com.tiancheng.trade.settlement.service.settlement.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tiancheng.trade.commom.core.data.PageInfo;
import com.tiancheng.trade.commom.web.feign.PaymentFeignService;
import com.tiancheng.trade.settlement.enums.*;
import com.tiancheng.trade.settlement.exception.BaseException;
import com.tiancheng.trade.settlement.exception.BusinessException;
import com.tiancheng.trade.settlement.mapper.settlement.*;
import com.tiancheng.trade.settlement.model.settlement.*;
import com.tiancheng.trade.settlement.service.settlement.IPaymentBillService;
import com.tiancheng.trade.settlement.service.settlement.IPaymentOrderService;
import com.tiancheng.trade.settlement.util.*;
import com.tiancheng.trade.settlement.vo.settlement.admin.*;
import com.tiancheng.trade.settlement.vo.settlement.admin.res.PaymentBillSummaryResVO;
import com.tiancheng.trade.settlement.vo.settlement.api.FlowSubOrderVO;
import com.tiancheng.trade.settlement.vo.settlement.api.PaymentBillVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @Auther: liudong
 * @Date: 2024/3/31 10:33
 * @Param ${tags}
 * @Description:
 */
@Service
@Slf4j
public class PaymentBillService implements IPaymentBillService {
    @Autowired
    PaymentBillMapper paymentBillMapper;
    @Autowired
    PaymentOrderBankMapper bankMapper;
    @Autowired
    PaymentOrderFinishMapper finishMapper;
    @Autowired
    PaymentOrderMapper paymentOrderMapper;
    @Autowired
    PaymentFeignService paymentService;
    @Autowired
    IPaymentOrderService paymentOrderService;
    @Autowired
    FlowSubOrderMapper flowSubOrderMapper;
    @Autowired
    PaymentOrderBankDetailMapper paymentOrderBankDetailMapper;
    @Autowired
    private ObjectMapper objectMapper;
    @Resource
    private JacksonJsonUtil jacksonJsonUtil;
    @Autowired
    private PaymentOldSystemMapper paymentOldSystemMapper;

    @Override
    public int audit(List<PaymentBillHandleVO> list) throws BusinessException {

        Assert.isTrue(!(list == null || list.isEmpty()), "参数错误");
        int i = 0;
        for (PaymentBillHandleVO handleVO : list) {

            Assert.notNull(handleVO.getId(), "参数错误");
            PaymentOrderFinish param = new PaymentOrderFinish();
            param.setId(handleVO.getId());
            param.setVersion(handleVO.getVersion());
            param.setRemark(handleVO.getRemark());
            param.setLastUpdDt(LocalDateTime.now());
            param.setFinishStatus(PaymentBillAuditStatusEnum.FINISH.getCode());
            param.setReconciliationStatus(PaymentBillStatusEnum.UP_SUCCESS.getCode());
            param.setLastUpdBy(UserUtils.currentUserId());
            i += finishMapper.updateById(param);
        }
        return i;
    }

    @Override
    public int diffHandle(List<PaymentDiffHandleVO> list) {
        if (null == list || list.isEmpty()) {
            return 0;
        }
        int count = 0;
        for (PaymentDiffHandleVO vo : list) {
            FlowSubOrder flowSubOrder = new FlowSubOrder();
            flowSubOrder.setFlowId(vo.getFlowId());
            flowSubOrder.setSubOrderId(vo.getSubOrderId());
            if (StringUtils.isEmpty(vo.getErrorAmount())) {
                vo.setErrorAmount("0");
            }
            BigDecimal amount = new BigDecimal(vo.getErrorAmount()).multiply(new BigDecimal(100));
            flowSubOrder.setErrorAmount(amount.intValue());
            flowSubOrder.setErrorReasonCode(vo.getErrorReasonCode());
            flowSubOrder.setErrorReason(vo.getErrorReason());
            flowSubOrder.setErrorRemark(vo.getErrorRemark());
            flowSubOrder.setErrorHandle(UserUtils.currentUserName());
            int number = flowSubOrderMapper.diffHandle(flowSubOrder);
            count += number;
        }
        finishMapper.updateStatus(list.get(0).getFlowId());
        return count;
    }

    @Override
    public PaymentBill getPaymentBill(String flowId) {
        QueryWrapper<PaymentBill> conditions = new QueryWrapper<>();
        conditions.eq("flow_id", flowId);
        return paymentBillMapper.selectOne(conditions);
    }

    /**
     * 功能描述: 根据flowId判断流水记账表和流水待对账表是否有数据
     *
     * @param:flowId
     * @return:boolean
     * @auther: LiuDong
     * @date: 17:52 2024/4/28
     */
    public boolean checkSaveStatus(String flowId) {
        boolean status = false;
        PaymentBill bill = this.getPaymentBill(flowId);
        PaymentOrder order = paymentOrderService.getPaymentOrder(flowId);
        if (StringUtils.isEmpty(bill) && StringUtils.isEmpty(order)) {
            status = true;
        }
        return status;
    }

    /**
     * 功能描述:支付记账
     * 1、转化类
     * 2、计算手续费
     * 3、计算结算金额
     * 4、保存流水记账
     * 5、生成中心侧待对账数据
     *
     * @param:
     * @return:
     * @auther: LiuDong
     * @date: 10:38 2024/4/12
     */
    @Transactional
    @Override
    public int recordBill(PaymentBillVO accountVO) throws BaseException {
        Integer status = 0;//新增状态
        Integer serviceCharge = 0;//手续费
        Integer settlementAmount = 0;//结算金额
        Integer amount = 0;//支付金额/退款金额
        BigDecimal rate = accountVO.getSlottingRate();//通道费率
        if (TransactionTypeEnum.PAY.getCode().equals(accountVO.getTransactionType())) {
            amount = accountVO.getPayAmount();
        } else if (TransactionTypeEnum.REFUND.getCode().equals(accountVO.getTransactionType())) {
            amount = accountVO.getRefundAmount();
        }
        //计算手续费=交易金额（元）*费率，四舍五入保留2位
        if (!StringUtils.isEmpty(amount)) {
            //计算手续费
            serviceCharge = AmountUtil.getServiceCharge(amount, rate, accountVO.getTransactionType());
            //计算结算金额
            settlementAmount = AmountUtil.getSettlementAmount(amount, serviceCharge, accountVO.getTransactionType());
        }
        PaymentBill paymentBill = ObjectConvertUtil.convert(accountVO, PaymentBill.class).get();
        //如果流水记账表已经存在该flowId不再记账
        if (!this.checkSaveStatus(paymentBill.getFlowId())) {
            return 0;
        }
        paymentBill.setServiceCharge(serviceCharge);
        paymentBill.setSettlementAmount(settlementAmount);
        paymentBill.setRecordTime(LocalDateTime.now());
        paymentBill.setRate(rate);
        paymentBill.setDiscount(paymentBill.getDiscount() == null ? 0 : paymentBill.getDiscount());
        // 设置退款payAmount，用于对账时比较
        if (TransactionTypeEnum.REFUND.getCode().equals(accountVO.getTransactionType())) {
            paymentBill.setPayAmount(0 - amount);
        }
        log.info("流水记账 flow_id,data：{}", paymentBill.getFlowId(), JsonUtil.toJson(paymentBill));
        status = paymentBillMapper.insert(paymentBill);
        //记账成功生成待对账表数据
        if (status > 0) {
            PaymentOrder paymentOrder = ObjectConvertUtil.convert(accountVO, PaymentOrder.class).get();
            if (TransactionTypeEnum.REFUND.getCode().equals(accountVO.getTransactionType())) {
                paymentOrder.setPayAmount(0 - amount);
                paymentOrder.setPayTime(paymentBill.getRefundTime());
            }
            paymentOrder.setServiceCharge(serviceCharge);
            paymentOrder.setSettlementAmount(settlementAmount);
            paymentOrder.setRate(rate);
            paymentOrder.setReconciliationTime(paymentBill.getRecordTime());
            paymentOrder.setDiscount(paymentBill.getDiscount());
            log.info("流水待对账 flow_id,data：{}", paymentOrder.getFlowId(), JsonUtil.toJson(paymentOrder));
            paymentOrderMapper.insert(paymentOrder);
        }
        return status;
    }

    @Override
    public List<FlowSubOrderVO> querySubOrderByFlowId(String flowId) {
        if (StringUtils.isEmpty(flowId)) {
            return null;
        }
        QueryWrapper<FlowSubOrder> conditions = new QueryWrapper<>();
        conditions.eq("flow_id", flowId);
        List<FlowSubOrder> subOrders = flowSubOrderMapper.selectList(conditions);
        if (subOrders == null || subOrders.isEmpty()) {
            return null;
        }
        List<FlowSubOrderVO> list = new ArrayList<>();
        for (FlowSubOrder order : subOrders) {
            FlowSubOrderVO orderVo = ObjectConvertUtil.convert(order, FlowSubOrderVO.class).get();
            if (ErrorReasonEnum.CUSTOM.getCode().equals(orderVo.getErrorReason()) || ErrorReasonEnum.NORMAL.getCode().equals(orderVo.getErrorReason())) {
                orderVo.setErrorReason(ErrorReasonEnum.getDesc(orderVo.getErrorReason()));
            }
            list.add(orderVo);
        }

        return list;
    }

    @Override
    public PageInfo<PaymentOrderBankDetailVO> oldSystemDataListQuery(PaymentOldSystemQueryVO queryVO) {
        Page<PaymentBillSummaryResVO> page = new Page<>();
        page.setCurrent(queryVO.getCurrentPage());
        page.setSize(queryVO.getPageSize());
        try {
            IPage<PaymentOrderBankDetailVO> pageresult = paymentOrderBankDetailMapper.oldSystemDataListQuery(page, queryVO);
            for (PaymentOrderBankDetailVO vo : pageresult.getRecords()) {
                if (vo == null) {
                    break;
                }
                vo.setTransactionTypeCn(TransactionTypeEnum.getDesc(vo.getTransactionType()));
                vo.setPayWayCn(PayWayEnum.getDesc(vo.getPayWay()));
            }
            PageInfo.Pagination pagination = new PageInfo.Pagination(queryVO.getCurrentPage(), queryVO.getPageSize(), page.getTotal());
            return new PageInfo<>(pageresult.getRecords(), pagination);
        } catch (Exception e) {
            log.info("oldSystemDataListQuery方法出现异常：{}", e.getMessage());
        }
        return null;

    }

    @Override
    public int oldSystemDataHandle(PaymentOldSystemVO vo) {
        vo.setUser(UserUtils.currentUserName());
        int count = finishMapper.updateOldSystemDataStatus(vo);
        if (count > 0) {
            QueryWrapper<PaymentOrderFinish> conditions = new QueryWrapper<>();
            conditions.in("pay_channel_orderid", vo.getPayChannelOrderids());
            List<PaymentOrderFinish> subOrders = finishMapper.selectList(conditions);
            if (subOrders != null && !subOrders.isEmpty()) {
                try {
                    List<PaymentOldSystem> oldSystems = objectMapper.readValue(jacksonJsonUtil.toJson(subOrders), new TypeReference<List<PaymentOldSystem>>() {
                    });
                    return paymentOldSystemMapper.batchSave(oldSystems);
                } catch (Exception e) {
                    log.info("oldSystemDataHandle方法出现异常：{}", e.getMessage());

                }
            }
        }
        return 0;
    }


}
